---
author: hongbo
date: "2019-12-20"
previewImg:
badge: release
title: Announcing BuckleScript 7.0.2-dev.1
description: |
---

## Happy Holiday Release!

[bs-platform@7.0.2-dev.1](https://github.com/BuckleScript/bucklescript/pull/4062)
is released for testing!

Try it via

```
npm i -g bs-platform@7.0.2-dev.1
```

This release contains several bug fixes for
[refmt](https://github.com/facebook/reason)(updated from 3.5.1 to 3.5.4). We
also spent quite some time improving the compiler performance. For example, we
optimized our specialized hash based data structures, which means that we can
expect a 5% better build time performance. We would like to collect more
benchmark data, so we are happy for any feedback / benchmarks from our
community!

A highlighting feature is that we added Generalized Unboxed Support (so called
[@unboxed] annotations). Here's a short definition from the official OCaml
Manual:

> unboxed can be used on a type definition if the type is a single-field record
> or a concrete type with a single constructor that has a single argument. It
> tells the compiler to optimize the representation of the type by removing the
> block that represents the record or the constructor (i.e. a value of this type
> is physically equal to its argument). In the case of GADTs, an additional
> restriction applies: the argument must not be an existential variable,
> represented by an existential type variable, or an abstract type constructor
> applied to an existential type variable.

**Note**: The beforementioned restriction about GADTs only applies to OCaml's
native compiler, not to BuckleScript's JavaScript compilation. So we will get
the maximum value with less confusing error messages!

The exciting thing about this feature is that we will now have more ways of
expressing our programs in our typical type safe records and variants without
sacrificing on runtime performance ("zero cost interop").

The best way to understand this feature is by looking at the following
examples:

**Unboxed variants:**

```reason
[@unboxed]
type t = A(int);
let x = A(3);
```

will translate to following JS:

```js
var x = 3;
```

As you can see, we are "unboxing" the `int` value from the internal variant
representation, so the variant will get completely invisible to the runtime.
Great for e.g. mapping to stringly typed JavaScript enums!

**Unboxed Records (1 field only)**

```reason
[@unboxed]
type t2 = {f: string};
let x = {f: "foo"};
```

will translate to following JS:

```js
var x = "foo";
```

The same principle as with variants. Now a lot of people will probably ask:
"Why would I ever want a 1 field record?". There are multiple reasons, one of
them would be a `ref` type, which is just a syntax sugar for a `{ contents:
'a}` record.

Another use case is for expressing high rank polymorphism without cost:

```reason
[@unboxed]
type r = {f: 'a. 'a => 'a};
let map_pair = (r, (p1, p2)) => (r.f(p1), r.f(p2));
```

**Note:** `'a. 'a => 'a` describes a polymorphic function interface, where `'a`
can be called with many different types (e.g. `f(1)` and `f("hi")`). The
compiler will not try to lock `'a` for the first type it sees (e.g. the `int`)
on the first call site. The parameter `'a` is therefore polymorphic!

By `unboxing` those records with one polymorphic function, we will get rid of
[value restriction for our existing encoding of uncurried
function](https://github.com/BuckleScript/bucklescript/issues/4058), this will
be a major feature!

**Unboxed GADTs:**

Since GADTs are lesser known in Reason syntax, we also added some OCaml snippet
to get a better idea of how the example data structure is defined.

```reason
[@unboxed]
type t =
  | Any ('a) : t;

let array = [|Any(3), Any("a")|];
```

```ocaml
(* OCaml *)
type t =
  | Any : 'a -> t
[@@unboxed]

let array = [|Any 3; Any "a"|]
```

The examples above will translate to following JS:

```js
var array = [3, "a"];
```

As you can already tell, this feature will give us way better possibilities to
do interop with polymorphic array representations in JavaScript (without losing
any type safetiness!).

As a more concrete use-case, this will give users the possibility to define
types such as `int_or_string`.

**Note:** Even if this GADT `t` contains an ADT `Any`, it doesn't mean that
it's the same as `any` in TypeScript. An `Any` value is constrained to a
certain contract (`'a -> t`), the array `[|Any(3), Any("a")|]` is inferred as a
`array(t)`. When users try to use `Any` values, they need to unpack them,
process the value inside, and repack them again. Pretty neat, right?

### Conclusion

This release will introduce the `[@unbox]` annotation to give us better ways to
do zero cost interop with variants, records, higher kinded polymorphic
functions, and GADTs. Under the hood improvements will give us better
performance as well!

We are really excited about these changes, and we hope so are you. Please check
out our newest `bs-platform@7.0.2-dev.1` release and let us know if you find
any issues!

A detailed list of changes is available here:
https://github.com/BuckleScript/bucklescript/blob/master/Changes.md#702

Happy hacking!

### Appendix

**A sophiscated explanation on why `unboxed` lifts some OCaml's type system
limitations**

> structural types (objects, classes, polymorphic variants, functions, etc) in
> OCaml are regular types, ocaml always do the expansion when dealing with such
> types, there is some limitations for such structural types, for example, non
> regular definitions are not allowed. Non structural types (variants, records)
> does not have such limitations, with `unboxed`, we can use non structural
> types as an indirection without changing its runtime representations.
